﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using élénkPróbája.extentions;
using élénkPróbája.results;
using élénkPróbája.Test.dto;
using élénkPróbája.Test.extention;
using élénkPróbája.Test.helpers;
using élénkPróbája.validators;

namespace élénkPróbája.Test
{
    [TestClass]
    public class CustomValidatorTester
    {
        private TestValidator validator;
        public CustomValidatorTester()
        {
            validator = new TestValidator();
        }
        [TestMethod]
        public void Returns_single_failure()
        {
            validator.Custom(company => new ValidationFailure("Name", "Fail", null));
            var result = validator.Validate(new Company());

            result.IsValid.ShouldBeFalse();
            result.Errors[0].ErrorMessage.ShouldEqual("Fail");
            result.Errors[0].PropertyName.ShouldEqual("Name");
        }
        [TestMethod]
        public void Returns_single_failure_async()
        {
            validator.CustomAsync(person => hTask.FromResult(new ValidationFailure("Name", "Fail", null))); 

            var result = validator.ValidateAsync(new Company()).Result;

            result.IsValid.ShouldBeFalse();
            result.Errors[0].ErrorMessage.ShouldEqual("Fail");
            result.Errors[0].PropertyName.ShouldEqual("Name");
        }
        [TestMethod]
        public void When_the_lambda_returns_null_then_the_validation_should_succeed()
        {
            validator.Custom(company => null);
            var result = validator.Validate(new Company());

            result.IsValid.ShouldBeTrue();
        }
        [TestMethod]
        public void When_the_async_lambda_returns_null_then_the_validation_should_succeed()
        {
            validator.CustomAsync(person => hTask.FromResult<ValidationFailure>(null));
            var result = validator.ValidateAsync(new Company()).Result;

            result.IsValid.ShouldBeTrue();
        }
        [TestMethod]
        public void Perserves_property_chain_using_custom()
        {
            validator.RuleFor(x => x.Accounts).SetCollectionValidator(new NestedOrderValidator());
            var company = new Company {Accounts = new List<Account> {new Account()}};
            var result = validator.Validate(company);

            result.Errors.Single().PropertyName.ShouldEqual("Accounts[0].Balance");
        }

        #region InternalClasses
        private class NestedOrderValidator : AbstractValidator<Account>
        {
            public NestedOrderValidator()
            {
                Custom((x, ctx) => {
                    return new ValidationFailure(ctx.PropChain.BuildPropertyName("Balance"), "bar");
                });
            }
        }

        #endregion
    }
}
